<?php

namespace App\Services;

use App\Exceptions\CustomException;
use App\Models\ActiveApi;
use App\Models\Game;
use App\Models\GameRecommend;
use App\Models\GameTag;
use App\Models\GameTagRelation;
use App\Models\MasterUser;
use App\Models\Partner;
use common\enum\CommonEnum;
use common\enum\GameEnum;
use common\enum\MasterLogEnum;
use common\utils\SysCode;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class GameService
{
    // 最新标签
    const GAME_TAG_NEW = 1;
    // 热门标签
    const GAME_TAG_HOT = 2;

    static $apiActiveType = [
        GameEnum::GAME_HOME_PC => 'pc首页',
        GameEnum::GAME_EGAME_BANNER => '电子游艺banner',
        GameEnum::GAME_CARD_BANNER => '棋牌对战banner',
        GameEnum::GAME_EGAME_API => '电子游戏API',
        GameEnum::GAME_LIVE => '真人视讯banner',
        GameEnum::GAME_SPORT => '体育竞技banner',
        GameEnum::GAME_CARD_API => '棋牌对战API',
        GameEnum::GAME_LOTTERY => '彩票游戏'
    ];


    // 删除API活动
    public static function deleteApiActive($id)
    {
        //只有停用状态下才能进行删除操作
        $active = ActiveApi::find($id);
        if (!$active) {
            error_exit(SysCode::GAME_API_ACTIVE_NOT_EXIST);
        }
        if ($active['status'] != GameEnum::STATUS_STOP) {
            error_exit(SysCode::GAME_API_DELETE_ERROR);
        }
        $result = ActiveApi::where('id', $id)->update(['status' => GameEnum::STATUS_DELETE]);
        if (!$result) {
            error_exit(SysCode::FAILED);
        } else {//删除API活动写入日志
            $remark = str_replace('{:name}', $active['title'], MasterLogEnum::REMARK['api_activity_del']);
            MasterLogService::writeMasterLog(MasterLogEnum::API_ACTIVITY_DEL,MasterLogEnum::SUCCESS,$remark);
        }
        return $result;
    }

    // 修改API活动状态
    public static function updateApiActiveStatus($params)
    {
        $active = ActiveApi::find($params['id']);
        if (!$active) {
            error_exit(SysCode::GAME_API_ACTIVE_NOT_EXIST);
        }
        if ($params['status'] == GameEnum::STATUS_OPEN) {
            self::isAllowOpenApiActive($active['type'], $active['partner_id'], $active['begin_time'], $active['end_time']);
        }
        $res = ActiveApi::where(["id" => $params['id']])->update(["status" => $params['status']]);
        if ($res) {
            //启/停API活动写入日志
            $remark = str_replace(['{:type}', '{:name}'], [MasterLogEnum::START_AND_STOP[$params['status']], $active['title']], MasterLogEnum::REMARK['api_activity_status']);
            MasterLogService::writeMasterLog(MasterLogEnum::API_ACTIVITY_STATUS, MasterLogEnum::SUCCESS, $remark);
        } else {
            error_exit(SysCode::FAILED);
        }
        return [];
    }

    public static function isAllowOpenApiActive($type, $partnerId, $beginTime, $endTime)
    {
        //PC首页（同一时间范围内只能启用一个）、电子游戏API与棋牌对战API（一个api同一时间只能启用一个 ）;其他类型没有限制
        if ($type == GameEnum::GAME_EGAME_API || $type == GameEnum::GAME_CARD_API || $type == GameEnum::GAME_HOME_PC) {
            self::isExistOpenActive($type, $beginTime, $endTime, $partnerId);
        }
        //检验活动结束时间
        if(strtotime($endTime) <= time()){
            error_exit(SysCode::GAME_API_ACTIVE_TIME_EXPIRE);
        }
        return true;
    }

    // 修改API活动
    public static function updateApiActive($params)
    {
        $activeData = ActiveApi::find($params['id']);
        if ($activeData) {
            $result = ActiveApi::where('id', $params['id'])
                ->update([
                    'title' => $params['title'] ?? '',
                    'type' => $params['type'] ?? '',//活动类型
                    'partner_id' => $params['partner_id'] ?? '',
                    'partner_name' => $params['partner_name'] ?? '',
                    'begin_time' => $params['begin_time'] ?? '',
                    'end_time' => $params['end_time'] ?? '',
                    'link_pc' => $params['link_pc'] ?? '',//pc跳转链接
                    'link_h5' => $params['link_h5'] ?? '',//h5跳转链接
                    'img_pc' => $params['img_pc'] ?? '',
                    'img_h5' => $params['img_h5'] ?? '',
                    'location' => $params['location'] ?? '',
                    'status' => $params['status'] ?? ''
                ]);

            if (!$result) {
                error_exit(SysCode::FAILED);
            } else {
                self::addApiActiveUpdateLog($activeData, $params);
            }
            return [];
        }
        error_exit(SysCode::FAILED);
    }

    /**
     *编辑API写入日志
     */
    public static function addApiActiveUpdateLog($activeData, $params)
    {
        if (!empty($activeData)) {
            $activeData = $activeData->toArray();
        }
        $data   = [
            'old' => [
                MasterLogEnum::API_ACTIV['name']       => $activeData['title'] ?? '',
                MasterLogEnum::API_ACTIV['type']       => self::$apiActiveType[$activeData['type']] ?? '',
                MasterLogEnum::API_ACTIV['link_pc']       => $activeData['link_pc'] ?? '',
                MasterLogEnum::API_ACTIV['link_h5']       => $activeData['link_h5'] ?? '',
                MasterLogEnum::API_ACTIV['begin_time'] => $activeData['begin_time'] ?? '',
                MasterLogEnum::API_ACTIV['end_time']   => $activeData['end_time'] ?? '',
                MasterLogEnum::API_ACTIV['status']     => MasterLogEnum::START_AND_STOP[$activeData['status']],
            ],
            'new' => [
                MasterLogEnum::API_ACTIV['name']       => $params['title'] ?? '',
                MasterLogEnum::API_ACTIV['type']       => self::$apiActiveType[$params['type']] ?? '',
                MasterLogEnum::API_ACTIV['link_pc']       => $params['link_pc'] ?? '',
                MasterLogEnum::API_ACTIV['link_h5']       => $params['link_h5'] ?? '',
                MasterLogEnum::API_ACTIV['begin_time'] => $params['begin_time'] ?? '',
                MasterLogEnum::API_ACTIV['end_time']   => $params['end_time'] ?? '',
                MasterLogEnum::API_ACTIV['status']     => MasterLogEnum::START_AND_STOP[$params['status']],
            ],
        ];
        $remark = str_replace('{:name}', $activeData['title'], MasterLogEnum::REMARK['api_activity_edit']);
        MasterLogService::writeMasterLog(MasterLogEnum::API_ACTIVITY_EDIT, MasterLogEnum::SUCCESS, $remark, $data);
    }

    // API活动状-获取活动类型
    public static function getGameActive($params)
    {
        //停用过期的api活动
        self::updateExpireApiActiveStatus();
        $result = self::queryGameActive($params);
        $result['list'] = self::formatGameActive($result['list']);
        return $result;
    }

    //停用过期的api活动
    private static function updateExpireApiActiveStatus()
    {
        ActiveApi::where([
            ['end_time', '<=', date('Y-m-d H:i:s')],
            ['status', '=', CommonEnum::ENABLED],
        ])
        ->update(['status' => CommonEnum::DISABLE]);
    }

    public static function formatGameActive($data)
    {
        $creatorIds = array_unique(array_column($data, 'creator_id'));
        $masterUser = MasterUser::whereIn('id', $creatorIds)->get()->toArray();
        $creatorUser = array_column($masterUser, 'username', 'id');
        foreach ($data as $k => &$v) {
            $v['type'] = self::$apiActiveType[$v['type']];
            $v['creator_name'] = isset($creatorUser[$v['creator_id']]) ? $creatorUser[$v['creator_id']] : '';
        }
        return $data;
    }

    public static function queryGameActive($params)
    {
        $where[] = ['status', '!=', GameEnum::STATUS_DELETE];
        $page = isset($params['page']) ? $params['page'] : 1;
        $pageSize = isset($params['page_size']) ? $params['page_size'] : 20;
        if (isset($params['begin_time'])) {
            $where[] = ['end_time', ">=", date('Y-m-d 00:00:00', strtotime($params['begin_time']))];
        }
        if (isset($params['end_time'])) {
            $where[] = ['begin_time', "<=", date('Y-m-d 23:59:59', strtotime($params['end_time']))];
        }
        foreach ($params as $key => $value) {
            if (in_array($key, ['status', 'title'])) {
                $where[] = [$key, $value];
            }
        }
        $sql = ActiveApi::where($where)->orderBy('created_at', 'DESC');
        return get_page_data($sql, $page, $pageSize);
    }

    // API活动-获取活动类型
    public static function getGameActiveType()
    {
        return self::$apiActiveType;
    }

    /*
     *  新增API活动
     */
    public static function addApiActive($params)
    {
        $res = ActiveApi::insert([
            'title' => $params['title'] ?? '',
            'type' => $params['type'] ?? '',//活动类型
            'partner_id' => $params['partner_id'] ?? '',
            'partner_name' => $params['partner_name'] ?? '',
            'begin_time' => $params['begin_time'] ?? '',
            'end_time' => $params['end_time'] ?? '',
            'link_pc' => $params['link_pc'] ?? '',//pc跳转链接
            'link_h5' => $params['link_h5'] ?? '',//h5跳转链接
            'img_pc' => $params['img_pc'] ?? '',
            'img_h5' => $params['img_h5'] ?? '',
            'location' => $params['location'] ?? '',//1左下，2右下
            'status' => $params['status'] ?? '',
            'creator_id' => Auth::user()->id
        ]);

        if ($res) {
            //写入日志
            $remark = str_replace('{:name}', $params['title'], MasterLogEnum::REMARK['api_activity_add']);
            MasterLogService::writeMasterLog(MasterLogEnum::API_ACTIVITY_ADD, MasterLogEnum::SUCCESS, $remark);
        } else {
            error_exit(SysCode::FAILED);
        }
        return [];
    }

    public static function checkParams($params)
    {
        $partner_id = isset($params['partner_id']) ? $params['partner_id'] : 0;
        if ($partner_id) {
            if ($partner = Partner::find($params['partner_id'])) {
                $params['partner_name'] = $partner['name'];
            } else {
                error_exit(SysCode::PARTNER_NOT_EXIST);
            }
        }
        //PC首页（同一时间范围内只能启用一个）、电子游戏API与棋牌对战API（一个api同一时间只能启用一个 ）
        if ($params['status'] == GameEnum::STATUS_OPEN) {
            self::isAllowOpenApiActive($params['type'], $partner_id, $params['begin_time'], $params['end_time']);
        }
        return $params;
    }

    //检查是否有已开启的api活动
    public static function isExistOpenActive($type, $beginTime, $endTime, $partnerId = 0)
    {
        $obj = ActiveApi::where('type', $type)
            ->where([
                ['status', GameEnum::STATUS_OPEN],
                ['begin_time', '<', $endTime],
                ['end_time', '>', $beginTime],
            ]);
        if ($partnerId) {
            $obj->where('partner_id', $partnerId);
        }
        $active = $obj->first();
        if ($active) {
            error_exit(SysCode::GAME_API_ACTIVE_REPEAT, ['type' => self::$apiActiveType[$type]]);
        }
    }

    public static function getGameList($params, $page = 1, $size = 20)
    {
        $wheres = ['game.status' => CommonEnum::ENABLED];
        if (!empty($params['game_type'])) {
            $wheres[] = ['game.game_type', $params['game_type']];
        }
        if (!empty($params['partner_id'])) {
            $wheres[] = ['game.partner_id', $params['partner_id']];
        }
        if (!empty($params['tag_id'])) {
            $wheres[] = ['gtr.tag_id', $params['tag_id']];
        }
        if (!empty($params['game_name'])) {
            $wheres[] = ['game.name', 'like', '%' . $params['game_name'] . '%'];
        }
        $data = get_page_data(Game::leftJoin('game_tag_relation as gtr', 'gtr.game_id', '=', 'game.id')->select('game.id')->distinct()->where($wheres), $page, $size);
        $ids = array_column($data['list'], 'id');
        $data['list'] = Game::leftJoin('game_tag_relation as gtr', 'gtr.game_id', '=', 'game.id')
            ->leftJoin('game_tag as gt', 'gt.id', '=', 'gtr.tag_id')
            ->select([
                'game.id',
                'game.name',
                'game.img_url',
                'game.game_type',
                'game.created_at as online_time',
                'game.new_end_time',
                'game.hot_end_time',
                DB::raw("IFNULL(GROUP_CONCAT(gt.name), '') as tags"),
                DB::raw("IFNULL(GROUP_CONCAT(gt.id), '') as tag_ids"),
                'game.badge',
            ])
            ->whereIn('game.id', $ids)
            ->groupBy('game.id')
            ->get();
        return $data;
    }

    public static function updateGame($id, $attrs)
    {
        if (empty($attrs)) {
            error_exit(SysCode::INVALID_ARGUMENT);
        }
        $game  = Game::where(['id' => $id])->first();
        $result = Game::where(['id' => $id])->update($attrs);
        if ($result) {
            $remark = '';
            if (isset($attrs['badge']) && empty($attrs['hot_end_time']) && empty($attrs['new_end_time'])) {//修改热门标签写入日志
                $remark = str_replace(['{:type}', '{:game_type}', '{:game_name}', '{:game}'],
                    [MasterLogEnum::STATUS[$attrs['badge']],CommonEnum::GAME_SUFFIX[$game['game_type']] , $game['partner_name'], $game['name'] ],
                    MasterLogEnum::REMARK['game_tag_edit_switch']);
            } elseif (isset($attrs['hot_end_time']) && empty($attrs['badge']) && empty($attrs['new_end_time'])) {//修改最热写入日志
                $remark = str_replace(['{:game_type}', '{:game_name}', '{:game}', '{:type}', '{:before_time}', '{:after_time}'],
                    [CommonEnum::GAME_SUFFIX[$game['game_type']] , $game['partner_name'], $game['name'], MasterLogEnum::GAME_LABEL_TYPE['hot'],  $game['hot_end_time'], $attrs['hot_end_time']],
                    MasterLogEnum::REMARK['game_tag_edit_time']);
            } elseif (isset($attrs['new_end_time']) && empty($attrs['badge']) && empty($attrs['hot_end_time'])) {//修改最新写入日志
                $remark = str_replace(['{:game_type}', '{:game_name}', '{:game}', '{:type}', '{:before_time}', '{:after_time}'],
                    [CommonEnum::GAME_SUFFIX[$game['game_type']] , $game['partner_name'], $game['name'], MasterLogEnum::GAME_LABEL_TYPE['new'],  $game['new_end_time'], $attrs['new_end_time']],
                    MasterLogEnum::REMARK['game_tag_edit_time']);
            }
            MasterLogService::writeMasterLog(MasterLogEnum::GAME_LABEL_EDIT, MasterLogEnum::SUCCESS, $remark);
        }
        return $result;
    }

    public static function updateGameTag($id, $tags)
    {
        if (empty($tags)) {
            return error_exit(SysCode::INVALID_ARGUMENT);
        }
        $data = [];
        //写日志收集旧标签
        $oldLabel = GameTagRelation::from("game_tag_relation as a")
            ->leftJoin('game_tag as b', 'b.id', '=', 'a.tag_id')
            ->selectRaw("GROUP_CONCAT(b.name) as name")
            ->where(['a.game_id' => $id])
            ->get()->toArray();
        DB::beginTransaction();
        try {
            GameTagRelation::where(['game_id' => $id])->delete();
            $gtrs = [];
            foreach ($tags as $t) {
                $gtrs[] = [
                    'game_id' => $id,
                    'tag_id' => $t,
                ];
                // 最新
                if ($t == self::GAME_TAG_NEW) {
                    Game::where(['id' => $id])->update(['new_end_time' => Carbon::now()->addMonth()]);
                }
                // 热门
                if ($t == self::GAME_TAG_HOT) {
                    Game::where(['id' => $id])->update(['hot_end_time' => Carbon::now()->addMonth()]);
                }
            }
            GameTagRelation::insert($gtrs);
            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('updateGameTag Error');
            return error_exit(SysCode::INTERNAL_SERVER_ERROR);
        }
        $newLabel    = GameTag::whereIn('id', $tags)->selectRaw("GROUP_CONCAT(name) as name")->get();
        $gameData    = Game::where(['id' => $id])->first();
        $remark      = str_replace(['{:game_type}', '{:game_name}', '{:game}'],[CommonEnum::GAME_SUFFIX[$gameData['game_type']],  $gameData['partner_name'], $gameData['name']],MasterLogEnum::REMARK['game_tag_edit']);
        $oldLabel = !empty($oldLabel[0]['name']) ? $oldLabel[0]['name'] : '';
        $newLabel = !empty($newLabel[0]['name']) ? $newLabel[0]['name'] : '';
        $data['old'] = [$gameData['name'] => $oldLabel];
        $data['new'] = [$gameData['name'] => $newLabel];
        MasterLogService::writeMasterLog(MasterLogEnum::GAME_LABEL_UPDATA, MasterLogEnum::SUCCESS, $remark, $data);
        return [];
    }

    public static function getGameRecommend($params, $page = 1, $size = 20)
    {
        $query = GameRecommend::from('game_recommend as gr')
            ->leftJoin('master_user as mu', 'gr.creator_id', '=', 'mu.id')
            ->select([
                'gr.id',
                'gr.game_type',
                'gr.partner_name',
                'gr.game_name',
                'gr.created_at',
                'gr.start_time',
                'gr.end_time',
                DB::raw("IF(DATEDIFF(gr.end_time, NOW()) > 0, DATEDIFF(gr.end_time, NOW()), 0) AS day_left"),
                'mu.username',
                'gr.sort',
                'gr.status',
                'gr.remark',
            ]);
        $wheres = [];
        if (!empty($params['game_type'])) {
            $wheres[] = ['gr.game_type', $params['game_type']];
        }
        if (!empty($params['partner_id'])) {
            $wheres[] = ['gr.partner_id', $params['partner_id']];
        }
        if (isset($params['status'])) {
            $wheres[] = ['gr.status', $params['status']];
        }

        return get_page_data($query->where($wheres), $page, $size);
    }

    public static function updateGameRecommend($id, $attrs)
    {
        if (empty($attrs)) {
            error_exit(SysCode::INVALID_ARGUMENT);
        }
        $game = GameRecommend::where(['id' => $id])->first()->toArray();
        $result = GameRecommend::where(['id' => $id])->update($attrs);
        if ($result) {
            //添加启停日志
            if (isset($attrs['status']) && empty($attrs['start_time']) && empty($attrs['end_time']) && empty($attrs['sort'])) {
                $remark = str_replace(['{:type}', '{:game_type}', '{:game_name}', '{:game}'],
                    [MasterLogEnum::START_AND_STOP[$attrs['status']], CommonEnum::GAME_SUFFIX[$game['game_type']], $game['partner_name'], $game['game_name']],
                    MasterLogEnum::REMARK['game_recommend_switch']);
                MasterLogService::writeMasterLog(MasterLogEnum::GAME_START_AND_STOP, MasterLogEnum::SUCCESS, $remark);
            } else {
                //添加编辑日志
                $data   = [
                    'old' => [
                        MasterLogEnum::GAME_EDIT_ARRAY['start_time'] => $game['start_time'],
                        MasterLogEnum::GAME_EDIT_ARRAY['end_time']   => $game['end_time'],
                        MasterLogEnum::GAME_EDIT_ARRAY['sort']       => $game['sort'],
                        MasterLogEnum::GAME_EDIT_ARRAY['status']     => MasterLogEnum::START_AND_STOP[$game['status']],
                    ],
                    'new' => [
                        MasterLogEnum::GAME_EDIT_ARRAY['start_time'] => $attrs['start_time'],
                        MasterLogEnum::GAME_EDIT_ARRAY['end_time']   => $attrs['end_time'],
                        MasterLogEnum::GAME_EDIT_ARRAY['sort']       => $attrs['sort'],
                        MasterLogEnum::GAME_EDIT_ARRAY['status']     => MasterLogEnum::START_AND_STOP[$attrs['status']],
                    ],
                ];
                $remark = str_replace(['{:game_type}', '{:game_name}', '{:game}'],
                    [ CommonEnum::GAME_SUFFIX[$game['game_type']], $game['partner_name'], $game['game_name']],
                     MasterLogEnum::REMARK['game_recommend_edit']);
                MasterLogService::writeMasterLog(MasterLogEnum::GAME_EDIT, MasterLogEnum::SUCCESS, $remark, $data);
            }
        }
        return $result;
    }

    public static function addGameRecommend($ids, $startTime, $endTime, $status, $remark = '')
    {
        $user = Auth::user();
        if (empty($user)) {
            return error_exit(SysCode::USER_TOKEN_EXPIRE);
        }
        $grs = [];
        DB::beginTransaction();
        try {
            foreach ($ids as $game_id) {
                GameRecommend::where(['game_id' => $game_id])->delete();
                $game = Game::where(['id' => $game_id])->first();
                if (empty($game)) {
                    DB::rollBack();
                    error_exit(SysCode::INVALID_ARGUMENT);
                }
                $grs[] = [
                    'game_type' => $game['game_type'],
                    'partner_id' => $game['partner_id'],
                    'partner_name' => $game['partner_name'],
                    'game_id' => $game_id,
                    'game_name' => $game['name'],
                    'start_time' => $startTime,
                    'end_time' => $endTime,
                    'status' => $status,
                    'remark' => $remark,
                    'creator_id' => $user['id'],
                    'updater_id' => $user['id'],
                ];
            }
            GameRecommend::insert($grs);
            DB::commit();
        } catch (CustomException $e) {
            throw $e;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('addGameRecommend Error');
            return error_exit(SysCode::INTERNAL_SERVER_ERROR);
        }
        $games = [];
        foreach ($ids as $id) {
            $game = Game::where(['id' => $id])->first()->toArray();
            $games[$game['partner_name']]['type']        = CommonEnum::GAME_SUFFIX[$game['game_type']];
            $games[$game['partner_name']]['name']        = $game['partner_name'];
            $games[$game['partner_name']]['game_name'][] = $game['name'];
        }
        $remarks = [];
        foreach ($games as $val) {
            $remark    = str_replace(['{:game_type}', '{:game_name}', '{:game}'],
                [$val['type'], $val['name'], implode('、', $val['game_name'])],
                MasterLogEnum::REMARK['game_recommend_add']);
            $remarks[] = $remark;
        }
        MasterLogService::writeMasterLog(MasterLogEnum::GAME_ADD, MasterLogEnum::SUCCESS, implode(',', $remarks));
        return [];
    }

    public static function delGameRecommend($id)
    {
        $gameRecommend   = GameRecommend::where(['id' => $id])->first();
        $game   = Game::where(['id' => $gameRecommend['game_id']])->first();
        $result = GameRecommend::where(['id' => $id])->delete();
        if ($result) {
            //添加删除推荐游戏日志
            $remark = str_replace(['{:game_type}', '{:game_name}', '{:game}'],
                [ CommonEnum::GAME_SUFFIX[$game['game_type']], $game['partner_name'], $gameRecommend['game_name']],
                MasterLogEnum::REMARK['game_recommend_del']);
            MasterLogService::writeMasterLog(MasterLogEnum::GAME_DEL, MasterLogEnum::SUCCESS, $remark);
        }
        return $result;
    }

    //获取api或者游戏名称
    public static function getPartnerFullName($partName, $gameType)
    {
        $partName = strtoupper($partName);
        $gameSuffix = CommonEnum::GAME_SUFFIX;
        $specailGameName = CommonEnum::SPECIAL_GAME_SUFFIX;
        //兼容同一个api可以根据不同gameType设置不同名称
        if (isset($specailGameName[$gameType]) && is_array($specailGameName[$gameType]) && array_key_exists($partName, $specailGameName[$gameType])) {
            return $specailGameName[$gameType][$partName];
        }
        $gameTypeList = array_keys($gameSuffix);
        if (in_array($gameType, $gameTypeList)) {
            return $partName . $gameSuffix[$gameType];
        }
        return $partName;
    }
}
